package com.ssau.expert.core.util;

import com.ssau.expert.common.RuleDTO;
import com.ssau.expert.core.impl.VariableTable;
import com.ssau.expert.core.model.Condition;
import com.ssau.expert.core.model.FuzzyRule;
import com.ssau.expert.core.model.Operation;
import com.ssau.expert.entity.ShipName;
import com.ssau.expert.entity.ShipProfile;
import com.ssau.expert.util.Names;

import java.util.ArrayList;
import java.util.List;

/**
 * Author: Sergey42
 * Date: 05.12.13 13:07
 */
public class RuleDTOParser {

    static String AND = " && ";

    public static FuzzyRule[] parse(RuleDTO dto) {
        FuzzyRule[] fuzzyRules = new FuzzyRule[2];
        fuzzyRules[0] = parse(dto, 0);
        //fuzzyRules[1] = parse(dto, 4);
        return fuzzyRules;
    }

    public static FuzzyRule parse(RuleDTO dto, int dx) {
        VariableTable table = VariableTable.get();

        FuzzyRule rule = new FuzzyRule();

        rule.setRuleDTO(dto);
        rule.setId(String.valueOf(dto.id) + "." + (dx == 0 ? "1" : "2"));
        rule.setOutputVariable(table.getVariable(Names.RESULT));

        String shipString = (String) dto.values[RuleDTO.SHIP];
        String[] shipsSplit = shipString.split(",");
        String ruleOutput = "[";
        for (String shipSplit : shipsSplit) {
            if ("".equals(shipSplit) || "null".equals(shipSplit)) {
                continue;
            }
            int id = Integer.valueOf(shipSplit);
            ShipName shipName = ShipName.fromId(id);
            ruleOutput += "\"" + shipName.getLocalName() + "\",";

        }
        ruleOutput = "[".equals(ruleOutput) ? "[]" : ruleOutput.substring(0, ruleOutput.length() - 1) + "]";
        rule.setRuleOutput("r := " + ruleOutput);

        List<Condition> conditions = new ArrayList<>();

        int profileId = (int) dto.values[RuleDTO.PROFILE];
        ShipProfile shipProfile = ShipProfile.fromId(profileId);

        StringBuilder ruleString = new StringBuilder("IF ");

        Condition conditionProfile = new Condition();
        conditionProfile.setConditionString(String.format("PR == \"%s\"", shipProfile.getName()));
        conditionProfile.setConditionValue("\"" + shipProfile.getName() + "\"");
        conditionProfile.setOperation(Operation.EQUAL);
        conditionProfile.setVariable(table.getVariable(Names.PROFILE));
        conditions.add(conditionProfile);

        ruleString.append(conditionProfile.getConditionString());
        ruleString.append(AND);

        Condition conditionDL1 = new Condition();
        conditionDL1.setConditionString(Names.DISTANCE.toLowerCase() + " > " + String.valueOf(dto.values[RuleDTO.A_L + dx]));
        conditionDL1.setConditionValue(String.valueOf(dto.values[RuleDTO.A_L + dx]));
        conditionDL1.setOperation(Operation.MORE);
        conditionDL1.setVariable(table.getVariable(Names.DISTANCE));
        conditions.add(conditionDL1);

        ruleString.append(conditionDL1.getConditionString());
        ruleString.append(AND);

        Condition conditionDR1 = new Condition();
        conditionDR1.setConditionString(Names.DISTANCE.toLowerCase() + " <= " + String.valueOf(dto.values[RuleDTO.A_R + dx]));
        conditionDR1.setConditionValue(String.valueOf(dto.values[RuleDTO.A_R + dx]));
        conditionDR1.setOperation(Operation.LESS_EQUAL);
        conditionDR1.setVariable(table.getVariable(Names.DISTANCE));
        conditions.add(conditionDR1);

        ruleString.append(conditionDR1.getConditionString());
        ruleString.append(AND);

        Condition conditionSL1 = new Condition();
        conditionSL1.setConditionString(Names.STUFF.toLowerCase() + " > " + String.valueOf(dto.values[RuleDTO.S_L + dx]));
        conditionSL1.setConditionValue(String.valueOf(dto.values[RuleDTO.S_L + dx]));
        conditionSL1.setOperation(Operation.MORE);
        conditionSL1.setVariable(table.getVariable(Names.STUFF));
        conditions.add(conditionSL1);

        ruleString.append(conditionSL1.getConditionString());
        ruleString.append(AND);

        Condition conditionSR1 = new Condition();
        conditionSR1.setConditionString(Names.STUFF.toLowerCase() + " <= " + String.valueOf(dto.values[RuleDTO.S_R + dx]));
        conditionSR1.setConditionValue(String.valueOf(dto.values[RuleDTO.S_R + dx]));
        conditionSR1.setOperation(Operation.LESS_EQUAL);
        conditionSR1.setVariable(table.getVariable(Names.STUFF));
        conditions.add(conditionSR1);

        ruleString.append(conditionSR1.getConditionString());

        ruleString.append(" THEN ");
        ruleString.append("R := ").append(ruleOutput);

        rule.setConditions(conditions);
        rule.setOutputVariable(table.getVariable(Names.RESULT));

        System.out.println("Build rule : " + ruleString.toString());
        rule.setRuleString(ruleString.toString());

        return rule;
    }
}
